import 'package:bot_toast/bot_toast.dart';
import 'package:dio/dio.dart' as dio;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:wan_android_flutter/common/base/base_page.dart';
import 'package:wan_android_flutter/common/resources/colors/theme_data_extension.dart';
import 'package:wan_android_flutter/common/resources/text_styles.dart';

import '../../generated/locales.g.dart';
import '../widget/common_loading.dart';

class HttpUtil {
  // 单例模式
  static final HttpUtil _instance = HttpUtil._internal();

  factory HttpUtil() => _instance;

  HttpUtil._internal() {
    _init();
  }

  late dio.Dio _dio;
  final List<dio.Interceptor> _interceptors = []; // 自定义拦截器列表
  dio.CancelToken _cancelToken = dio.CancelToken(); // 用于取消请求

  // 初始化
  void _init() {
    _dio = dio.Dio(dio.BaseOptions(
      baseUrl: "https://www.wanandroid.com", // 默认基础地址
      connectTimeout: const Duration(seconds: 10), // 连接超时时间
      receiveTimeout: const Duration(seconds: 10), // 接收数据超时时间
    ));

    // 添加默认拦截器
    _dio.interceptors.add(dio.InterceptorsWrapper(
      onRequest: (options, handler) {
        if (kDebugMode) {
          print('Request: ${options.method} ${options.path}');
        }
        return handler.next(options);
      },
      onResponse: (response, handler) {
        if (kDebugMode) {
          print('Response: ${response.statusCode} ${response.data}');
        }
        return handler.next(response);
      },
      onError: (dio.DioException e, handler) {
        if (kDebugMode) {
          print('Error: ${e.message}');
        }
        return handler.next(e);
      },
    ));

    // 添加自定义拦截器
    for (var interceptor in _interceptors) {
      _dio.interceptors.add(interceptor);
    }
  }

  // 添加自定义拦截器
  void addInterceptor(dio.Interceptor interceptor) {
    _interceptors.add(interceptor);
    _dio.interceptors.add(interceptor);
  }

  // 动态更新基础配置
  void updateBaseConfig({
    String? baseUrl,
    Duration? connectTimeout,
    Duration? receiveTimeout,
    Map<String, dynamic>? headers,
  }) {
    _dio.options.baseUrl = baseUrl ?? _dio.options.baseUrl;
    _dio.options.connectTimeout = connectTimeout ?? _dio.options.connectTimeout;
    _dio.options.receiveTimeout = receiveTimeout ?? _dio.options.receiveTimeout;
    _dio.options.headers = headers ?? _dio.options.headers;
  }

  // GET请求
  Future<dio.Response> get(String path,
      {Map<String, dynamic>? queryParameters,
      dio.Options? options,
      dio.CancelToken? cancelToken,
      bool showLoading = true}) async {
    return _request(path,
        method: 'GET',
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
        showLoading: showLoading);
  }

  // POST请求
  Future<dio.Response> post(String path,
      {dynamic data,
      Map<String, dynamic>? queryParameters,
      dio.Options? options,
      dio.CancelToken? cancelToken,
      bool showLoading = true}) async {
    return _request(path,
        method: 'POST',
        data: data,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
        showLoading: showLoading);
  }

  // PUT请求
  Future<dio.Response> put(String path,
      {dynamic data,
      Map<String, dynamic>? queryParameters,
      dio.Options? options,
      dio.CancelToken? cancelToken,
      bool showLoading = false}) async {
    return _request(path,
        method: 'PUT',
        data: data,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
        showLoading: showLoading);
  }

  // DELETE请求
  Future<dio.Response> delete(String path,
      {dynamic data,
      Map<String, dynamic>? queryParameters,
      dio.Options? options,
      dio.CancelToken? cancelToken,
      bool showLoading = false}) async {
    return _request(path,
        method: 'DELETE',
        data: data,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
        showLoading: showLoading);
  }

  // 文件上传
  Future<dio.Response> upload(
    String path, {
    required String filePath,
    Map<String, dynamic>? data,
    Map<String, dynamic>? queryParameters,
    dio.Options? options,
    dio.CancelToken? cancelToken,
  }) async {
    final formData = dio.FormData.fromMap({
      ...data ?? {},
      'file': await dio.MultipartFile.fromFile(filePath),
    });
    return _request(
      path,
      method: 'POST',
      data: formData,
      queryParameters: queryParameters,
      options: options,
      cancelToken: cancelToken,
    );
  }

  // 文件下载
  Future<dio.Response> download(String urlPath, String savePath,
      {Map<String, dynamic>? queryParameters,
      dio.Options? options,
      dio.CancelToken? cancelToken,
      bool showLoading = false}) async {
    try {
      final response = await _dio.download(
        urlPath,
        savePath,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken ?? _cancelToken,
      );
      return response;
    } on dio.DioException catch (e) {
      throw _handleError(e);
    }
  }

  // 通用请求方法
  Future<dio.Response> _request(String path,
      {required String method,
      dynamic data,
      Map<String, dynamic>? queryParameters,
      dio.Options? options,
      dio.CancelToken? cancelToken,
      bool showLoading = false}) async {
    CancelFunc? cancelFunc;
    try {
      if (showLoading) {
        cancelFunc = showCommonLoading(
          loadingText: LocaleKeys.requesting.tr,
          style: Theme.of(Get.context!).colorData.textBlack.s16.regular
        );
      }
      dio.Options requestOption;
      if (options != null) {
        options.method = method;
        requestOption = options;
      } else {
        requestOption = dio.Options(method: method);
      }
      final response = await _dio.request(
        path,
        data: data,
        queryParameters: queryParameters,
        options: requestOption,
        cancelToken: cancelToken ?? _cancelToken,
      );
      return response;
    } on dio.DioException catch (e) {
      throw _handleError(e);
    } finally {
      // 关闭弹窗
      if (showLoading) {
        cancelFunc?.call();
      }
    }
  }

  // 取消请求
  void cancelRequests({dio.CancelToken? cancelToken}) {
    if (cancelToken == null) {
      _cancelToken.cancel('Request cancelled');
      _cancelToken = dio.CancelToken(); // 重置CancelToken
    } else {
      cancelToken.cancel('Request cancelled');
    }
  }

  // 错误处理
  String _handleError(dio.DioException e) {
    switch (e.type) {
      case dio.DioExceptionType.connectionTimeout:
        return '连接超时';
      case dio.DioExceptionType.sendTimeout:
        return '发送请求超时';
      case dio.DioExceptionType.receiveTimeout:
        return '接收数据超时';
      case dio.DioExceptionType.badResponse:
        return '服务器返回错误: ${e.response?.statusCode}';
      case dio.DioExceptionType.cancel:
        return '请求已取消';
      case dio.DioExceptionType.unknown:
        return '未知错误: ${e.message}';
      default:
        return '网络错误: ${e.message}';
    }
  }

  CancelFunc showCommonLoading({
    String loadingText = "",
    Alignment? align = Alignment.center,
    crossPage = true,
    backButtonBehavior = BackButtonBehavior.ignore,
    bool clickClose = false,
    VoidCallback? onClose,
    Color? barrierColor,
    Color? backgroundColor,
    Color? circleColor,
    BoxConstraints? constraints,
    TextStyle? style,
  }) {
    return BotToast.showCustomLoading(
      align: align,
      onClose: onClose,
      clickClose: clickClose,
      backButtonBehavior: backButtonBehavior,
      crossPage: crossPage,
      backgroundColor: barrierColor ?? Colors.transparent,
      toastBuilder: (f) {
        return CommonLoading(
          loadingText: loadingText,
          backgroundColor: backgroundColor,
          circleColor: circleColor,
          constraints: constraints,
          style: style,
        );
      },
      animationDuration: const Duration(milliseconds: 250),
      animationReverseDuration: const Duration(milliseconds: 200),
    );
  }
}

/// HttpUtil工具类
HttpUtil httpUtil = HttpUtil();
